/*
** Copyright (c) 2010 by Lorimark Solutions, LLC.
** All Rights Reserved.
** Send inquiries to: info@lorimarksolutions.com
**
*/

#include <eviesystems.h>
#include <font3x5.h>
#include <mega48serial.h>
#include <serial.h>
#include <packet.h>
#include <crc8.h>
#include "lcd.h"
#include "bargraph.h"

#define LED (1<<PD5)
#define DB1 (1<<PD4)
#define DB2 (1<<PD3)

#define FLPDB1 PORTD ^= DB1
#define TOGDB1 FLPDB1; /* _delay_us(1); */ FLPDB1

#define FLPDB2 PORTD ^= DB2
#define TOGDB2 FLPDB2; /* _delay_us(1); */ FLPDB2

#define LED_FLASH_LONG  250
#define LED_FLASH_SHORT 15

uint16 batteries[32];
uint16 battery;

uint16 ledFlash;
uint8  ledState;

ISR(TIMER1_OVF_vect)
{
  if( !ledFlash-- )
  {
//    PORTD ^= LED;

    if( ledState )
    {
      PORTD     = PIND | LED;
      ledFlash  = LED_FLASH_LONG;
      ledState  = 0;
    }
    else
    {
      PORTD     = PIND & ~LED;
      ledFlash  = LED_FLASH_SHORT;
      ledState  = 1;
    }
  }
}

void init_timer(void)
{

  sei();

  TCCR1A = 
    (0b00   << COM1A0) | // 6.Compare Output Mode for A
    (0b00   << COM1B0) | // 4.Compare Output Mode for B 
    (0b00   << WGM10)  ; // 0.Waveform Generation Mode

  TCCR1B = 
    (0b0    << ICNC1)  | // 7.Input Capture Noise Canceler
    (0b0    << ICES1)  | // 6.Input Capture Edge Select
    (0b00   << WGM12)  | // 3.Waveform Generation Mode
    (0b001  << CS10)   ; // 0.Clock Select (1=no prescaling)

  TCCR1C =
    (0b0    << FOC1A)  | // 7.Force Output Compare for A
    (0b0    << FOC1B)  ; // 6.Force Output Compare for B

  TIMSK1 = 
    (0b0    << ICIE1)  | // 5.Input Capture Interrupt Enable
    (0b0    << OCIE1B) | // 2.Output Compare B Match Interrupt Enable
    (0b0    << OCIE1A) | // 1.Output Compare A Match Interrupt Enable
    (0b1    << TOIE1)  ; // 0.Overflow Interrupt Enable

//  OCR1AH = (20000>>8);
//  OCR1AL = (20000&255);

}


/*************************************************************************/
/*************************************************************************/
/*************************************************************************/

uint16 xyzzy;
#define VOFFSET 350

void showBatteries(void)
{
  uint8 bi; bi = (packet.src - 1) * 4;

//  writeHexNumber_lcd( 0, xyzzy++ );

  battery = (packet.dat[0]*256) + packet.dat[1];
//  battery -= VOFFSET;
//  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = (packet.src-1) * 16;
//    lcd_y = 18;
//    printf( putc_lcd, "%04lu", battery );
    drawBar( bi, battery );
//    drawBar( bi, xyzzy++ );
  }

//  writeHexNumber_lcd( -1, battery );

  ++bi;
  battery = (packet.dat[2]*256) + packet.dat[3];
//  battery -= VOFFSET;
//  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = 1 * 2 * 5 + (bi * 32);
//    lcd_y = 18;
//    printf( putc_lcd, "%02lu", battery );
    drawBar( bi, battery );
//    drawBar( bi, xyzzy++ );
  }

//  writeHexNumber_lcd( -1, battery );

  ++bi;
  battery = (packet.dat[4]*256) + packet.dat[5];
//  battery -= VOFFSET;
//  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = 2 * 2 * 5 + (bi * 32);
//    lcd_y = 18;
//    printf( putc_lcd, "%02lu", battery );
    drawBar( bi, battery );
//    drawBar( bi, xyzzy++ );
  }

//  writeHexNumber_lcd( -1, battery );

  ++bi;
  battery = (packet.dat[6]*256) + packet.dat[7];
//  battery -= VOFFSET;
//  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = 3 * 2 * 5 + (bi * 32);
//    lcd_y = 18;
//    printf( putc_lcd, "%02lu", battery );
    drawBar( bi, battery );
//    drawBar( bi, xyzzy++ );
  }

//  writeHexNumber_lcd( -1, battery );

}

void zapBatteries(void)
{
  drawBar( 0, 0 );
  drawBar( 1, 0 );
  drawBar( 2, 0 );
  drawBar( 3, 0 );
}


/*************************************************************************/
/*************************************************************************/
/*************************************************************************/





uint8 ProcessNetworkResponse(void)
{
  if( !rxNetworkPacket() ) return( 0 );

  /* * * * * * * * * * * * * * * * * * * * * * *
  ** At this point we have a valid packet and it
  **  is addressed to us.  We can now process the
  **  data in it and do whatever is requested.
  **
  */

  /*
  ** Switch on the command
  **
  */
  switch( packet.cmd )
  {
    /*
    ** This is a command to read out all the data
    **
    */
    case 1:
    {
      showBatteries();
      return(1);
    }
  }

//  printf( putc_lcd, "no cmd  " );
  return(0);

}



void WaitForAnswer(void)
{
  uint8 timeout = 5;

  while( !ProcessNetworkResponse() && timeout-- )
  {
    _delay_ms(2);
  }
}


/*************************************************************************/
/*************************************************************************/
/*************************************************************************/





uint8 target;
uint8 x;

int main(void)
{

//  _delay_ms(1000);

  DDRD |= LED;
  DDRD |= DB1;
  DDRD |= DB2;

  PORTD |= LED;


  /*
  ** Initialize the world
  **
  */
  init_timer();
  init_usart();
  init_lcd(1);

  nodeID[0] = 100;

//  puts_lcd( "evie-systems LCD48-01" );

  /*
  ** Let'r rip!
  **
  */
  ENABLE_INTERRUPTS;

  _delay_ms(1000);

  /*
  ** Main Control Loop
  **
  */
  forever
  {

    for( target=1; target<9; target++ )
    {
      crc8Result = 0;
      txPut( ':'        );
      txPut( target     );
      txPut( nodeID[0]  );
      txPut( 1          );
      txPut( 0          );
      txPut( crc8Result );

      WaitForAnswer();
    }


#ifdef NEVER
    for( target=0; target<32; target++ )
    {
      drawBar( target, x );

      _delay_ms(10);

      x++;
      if( x > 45 ) x = 0;

    }
#endif


  }
}

